import { Browser, HTTPResponse, launch, Page, Target } from "puppeteer";
import { v4 } from "uuid";
import { ProxyBrowser, ProxyCookies, ProxyUser, useEntityManager } from "./entities";
import dayjs from "dayjs";
const browserMap: Map<string, Browser> = new Map();
export function getId(target: any) {
    if (!target) return;
    return target.id;
}
export function setId(target: any, id: string) {
    if (!target) return;
    target.id = id;
}
export async function getBrowser(clientId: string) {
    return await useEntityManager(async m => {
        const browser = await m.findOne(ProxyBrowser, { where: { client_id: clientId } })
        if (browser) {
            const instance = browserMap.get(browser.uuid)
            if (instance) return instance;
            await m.delete(ProxyBrowser, browser.uuid)
        }
        return createBrowser(clientId)
    })
}
export const createBrowser = async (clientId: string) => {
    // 一个浏览器 一个routing
    const browser = await launch({
        headless: false,
        defaultViewport: {
            width: 1920,
            height: 1080,
            deviceScaleFactor: 1
        },
        args: ['--no-sandbox', '--disable-setuid-sandbox', '--user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36"']
    });
    const uuid = v4();
    await useEntityManager(async m => {
        const entity = m.create(ProxyBrowser, {
            uuid,
            client_id: clientId
        });
        await m.save(ProxyBrowser, entity);
        browserMap.set(uuid, browser)
    });
    setId(browser, uuid)
    return browser;
}

const pageMap: Map<string, Page> = new Map();
export interface BrowserOptions {
    onResponse?: (response: HTTPResponse) => void;
}
export const createBrowserPage = async (clientId: string, url: string, options?: BrowserOptions): Promise<[Page, Browser]> => {
    const browser = await getBrowser(clientId)
    const ctx = browser.defaultBrowserContext();
    await ctx.overridePermissions(url, ['geolocation'])
    const page = await browser.newPage()
    await page.setJavaScriptEnabled(true);
    const uuid = v4()
    setId(page, uuid)
    pageMap.set(uuid, page);
    browser.on('*', async (...args: any[]) => {
        if (args && args.length > 0) {
            const [type, payload] = args;
            if (type === 'targetcreated') {
                const target: Target = payload;
                const type = target.type()
                if (type === 'page') {
                    const page = await target.asPage()
                    page.on('*', (...args: any[]) => {
                        if (args && args.length > 0) {
                            const [type, payload] = args;
                            if (type === 'response') {
                                if (options && options.onResponse) {
                                    options.onResponse(payload)
                                }
                            }
                        }
                    })
                }
            }
        }
    })
    page.on('*', (...args: any[]) => {
        if (args && args.length > 0) {
            const [type, payload] = args;
            if (type === 'response') {
                if (options && options.onResponse) {
                    options.onResponse(payload)
                }
            }
        }
    });
    // 获取cookie
    await useEntityManager(async m => {
        const user = await m.findOne(ProxyUser, { where: { login_at: clientId } })
        if (user) {
            const cookies = await m.find(ProxyCookies, { where: { user_id: user.uuid } })
            await page.setCookie(...cookies.map(c => {
                return {
                    name: c.name,
                    value: c.value,
                    domain: c.domain,
                    path: c.path,
                };
            }))
        }
    })
    await page.goto(url, { waitUntil: 'networkidle2' })
    return [page, browser];
}